﻿using System;
using System.Runtime.Serialization;
	
namespace ThePresenter.Data
{
	[Serializable]
	public sealed class UID : ISerializable, IEquatable<UID>
	{
		#region Fields

		private Guid _guid;

		#endregion

		/// <summary>
		/// Initializes a new instance of the <see cref="UID"/> class.
		/// </summary>
		public UID()
		{
			_guid = Guid.NewGuid();
		}

		#region ToByteArrayConverter
		// used when adding uid as stroke property which can only be Byte[]

		/// <summary>
		/// Initializes a new instance of the <see cref="UID"/> class.
		/// </summary>
		/// <param name="b">The b.</param>
		public UID(byte[] b)
		{
			this._guid = new Guid(b);
		}

		/// <summary>
		/// Converts to the byte array.
		/// </summary>
		/// <returns>Byte[] representation of UID</returns>
		public byte[] ToByteArray()
		{
			return _guid.ToByteArray();
		}
		#endregion

		/// <summary>
		/// Returns a <see cref="System.String"/> that represents this instance.
		/// </summary>
		/// <returns>
		/// A <see cref="System.String"/> that represents this instance.
		/// </returns>
		public override string ToString()
		{
			return _guid.ToString();
		}

		#region ISerializable Members

		/// <summary>
		/// Initializes a new instance of the <see cref="UID"/> class.
		/// </summary>
		/// <param name="info">The <see cref="System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
		/// <param name="context">The <see cref="System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination. .</param>
		public UID(SerializationInfo info, StreamingContext context)
		{
			_guid = new Guid((byte[])info.GetValue("Guid", typeof(byte[])));
		}

		/// <summary>
		/// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
		/// </summary>
		/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
		/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization.</param>
		/// <exception cref="T:System.Security.SecurityException">
		/// The caller does not have the required permission.
		/// </exception>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Guid", _guid.ToByteArray(), typeof(byte[]));
		}

		#endregion

		/// <summary>
		/// Returns a hash code for this instance.
		/// </summary>
		/// <returns>
		/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
		/// </returns>
		public override int GetHashCode()
		{
			return _guid.GetHashCode();
		}

		/// <summary>
		/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
		/// </summary>
		/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
		/// <returns>
		/// 	<c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
		/// </returns>
		/// <exception cref="T:System.NullReferenceException">
		/// The <paramref name="obj"/> parameter is null.
		/// </exception>
		public override bool Equals(object obj)
		{
			return this.Equals(obj as UID);
		}

		#region IEquatable<Uid> Members

		/// <summary>
		/// Indicates whether the current object is equal to another object of the same type.
		/// </summary>
		/// <param name="other">An object to compare with this object.</param>
		/// <returns><c>true</c> if the current object is equal to the other parameter; otherwise, <c>false</c>.</returns>
		public bool Equals(UID other)
		{
			return object.Equals(this._guid, other);
		}

		#endregion
	}
}
